﻿using log4net;
using Prism.Ioc;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Media3D;
using System.Windows.Threading;

namespace System
{
    public class TopmostHelper
    {
        #region Fields
        private readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private readonly List<int> _runProcesseIds = new List<int>();
        private bool _isEnableTopmost;
        private int _isInit;
        private Process _process;

        public const string TopmostKey = "Topmost";
        private static TopmostHelper _instance;
        public static TopmostHelper Instance => _instance ?? (_instance = ContainerLocator.Container.Resolve<TopmostHelper>());
        #endregion

        public event Action<bool> SetHotkeyState;

        #region Surface
        /// <summary>
        /// 初始化
        /// </summary>
        public void Initialize()
        {
            _isEnableTopmost = ConfigurationManager.AppSettings[TopmostKey].ToBool();
            SetMainWindowTopmost(_isEnableTopmost);
            StartTask();
        }

        /// <summary>
        /// 设置快捷可用性
        /// </summary>
        public void SetHotkeyEnabled(bool isEnabled = false)
        {
            SetHotkeyState?.Invoke(isEnabled);
        }

        public void AddProcesse(Process process, Rect rect = new Rect(), bool isTopmost = false)
        {
            if (process == null)
                return;
            _process = process;

            if (_isEnableTopmost)
            {
                SetMainWindowTopmost(false);
                _runProcesseIds.Add(process.Id);
                ShowProcess(process, rect, isTopmost);
            }
            else
            {
                //禁用Topmost时，单独设置进程为置前
                ShowProcess(_process, rect, isTopmost);
            }
        }

        public void RemoveProcess(Process process)
        {
            if (process != null)
            {
                _runProcesseIds.Remove(process.Id);
            }

            VerifyProcessList();
        }

        /// <summary>
        /// 设置进程置前
        /// </summary>
        public async void ShowProcess(Process process, Rect rect = new Rect(), bool isTopmost = false)
        {
            if (process == null)
            {
                _logger.Debug($"Process is null");
                return;
            }
            if (process.MainWindowHandle == IntPtr.Zero)
            {
                for (int i = 0; i < 20; i++)
                {
                    //句柄为0时，可能程序还未启动，等待一会
                    if (process.MainWindowHandle != IntPtr.Zero)
                        break;
                    await Task.Delay(100);
                }
                if (process.MainWindowHandle == IntPtr.Zero)
                {
                    _logger.Debug($"Process MainWindowHandle is null");
                    return;
                }
            }
            AsyncActionHelper.RunDispatcherTask(() =>
            {
                WinApiHelper.ShowWindow(process.MainWindowHandle, WinApiHelper.SW_SHOWNORMAL);
                var isDefaultSize = rect.X == 0 && rect.Y == 0 && rect.Width == 0 && rect.Height == 0;
                //先置顶
                WinApiHelper.SetWindowPos(process.MainWindowHandle, WinApiHelper.HWND_TOPMOST,
                    (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height, isDefaultSize ? WinApiHelper.TOPMOST_FLAGS : WinApiHelper.SWP_SHOWWINDOW);
                //再设置
                WinApiHelper.SetWindowPos(process.MainWindowHandle, isTopmost ? WinApiHelper.HWND_TOPMOST : WinApiHelper.HWND_NOTOPMOST,
                    (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height, isDefaultSize ? WinApiHelper.TOPMOST_FLAGS : WinApiHelper.SWP_SHOWWINDOW);
                _logger.Debug($"Show Process->{process.ProcessName},{process.MainWindowHandle},{rect}");
            }, DispatcherPriority.Send, false);
        }
        #endregion

        #region Implements

        private void StartTask()
        {
            if (!_isEnableTopmost)
                return;
            if (Interlocked.CompareExchange(ref _isInit, 1, 0) != 0)
                return;
            AsyncActionHelper.RunTask(async () =>
            {
                while (true)
                {
                    while (_runProcesseIds.Any())
                    {
                        var tempGetProcesses = Process.GetProcesses().Select(s => s.Id);
                        _runProcesseIds.RemoveAll(r => !tempGetProcesses.Contains(r));
                        VerifyProcessList();
                        await Task.Delay(1000);
                    }
                    await Task.Delay(1000);
                }
            });
        }

        private void VerifyProcessList()
        {
            if (!_runProcesseIds.Any())
            {
                //列表为空时设置主程序为置顶
                SetMainWindowTopmost(_isEnableTopmost);
            }
        }

        /// <summary>
        /// 设置主程序Topmost状态
        /// </summary>
        private void SetMainWindowTopmost(bool isTopmost)
        {
            if (!_isEnableTopmost)
                return;
            AsyncActionHelper.RunDispatcherTask(() =>
            {
                if (isTopmost != Application.Current.MainWindow.Topmost)
                {
                    Application.Current.MainWindow.Topmost = isTopmost;
                    _logger.Debug($"Set MainWindow Topmost={isTopmost}");
                }
            }, DispatcherPriority.Send, false);
        }

        #endregion
    }
}
